#include <iostream>
#include <pthread.h>
#include <string>
#include <unistd.h>

int tickets = 10000;

class ThreadData
{
public:
    ThreadData(pthread_mutex_t *mutex, pthread_cond_t *cond, const std::string &name)
        : _mutex(mutex), _cond(cond), _threadname(name)
    {
    }
    pthread_mutex_t *_mutex;
    pthread_cond_t *_cond;
    std::string _threadname;
};

void *Routine(void *args)
{
    ThreadData *td = static_cast<ThreadData *>(args);
    while (true)
    {
        pthread_mutex_lock(td->_mutex);
        while (tickets <= 0)
        {
            std::cout << "没票了！！ " << td->_threadname << std::endl;
            pthread_cond_wait(td->_cond, td->_mutex);
        }

        usleep(1000);
        std::cout << td->_threadname << " get a ticket: " << tickets-- << std::endl;
        pthread_mutex_unlock(td->_mutex);
    }
    return nullptr;
}

int main()
{
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, nullptr);
    pthread_cond_t cond;
    pthread_cond_init(&cond, nullptr);

    pthread_t t1, t2, t3;
    ThreadData *td1 = new ThreadData(&mutex, &cond, "thread-1");
    ThreadData *td2 = new ThreadData(&mutex, &cond, "thread-2");
    ThreadData *td3 = new ThreadData(&mutex, &cond, "thread-3");

    pthread_create(&t1, nullptr, Routine, td1);
    pthread_create(&t2, nullptr, Routine, td2);
    pthread_create(&t3, nullptr, Routine, td3);

    while (true)
    {
        sleep(4);
        pthread_mutex_lock(&mutex);
        tickets += 1000;
        std::cout << "tickets += 1000 -- > " << tickets << std::endl;
        pthread_mutex_unlock(&mutex);
        pthread_cond_broadcast(&cond);
        // pthread_cond_signal(&cond);
    }

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    pthread_join(t1, nullptr);
    pthread_join(t2, nullptr);
    pthread_join(t3, nullptr);
    delete td1;
    delete td2;
    delete td3;
    return 0;
}